﻿
// ## 2023/05/09 # 铃 # 大幅优化逻辑,从723中抽取独立 ##
// ## 2023/03/19 # 铃 # 创建,目的是为了让AI在野战中撤退##

namespace AI兵团撤退
{
    bool 调试模式 = false;

    //=======================================================================================

    class Main
    {
        Main()
        {
            pk::bind(111, pk::trigger111_t(onTurnStart));
        }
        //---------------------------------------------------------------------------

        //---------------------------------------------------------------------------

        void onTurnStart(pk::force @force)
        {
            if (pk::is_campaign())
                return;

            if (!pk::is_normal_force(force))
                return;
            int force_id = pk::get_current_turn_force_id();
            if (!pk::is_normal_force(force_id))
                return;

            // 本势力全体部队
            pk::array<pk::unit @> arr_unit_list = pk::list_to_array(pk::get_unit_list(force));
            if (int(arr_unit_list.length) == 0)
                return;

            for (int i = 0; i < int(arr_unit_list.length); i++)
            {
                pk::unit @unit = arr_unit_list[i];
                if (pk::is_alive(unit) and unit.type == 部队类型_战斗 and unit.order != 部队任务_撤退 and !pk::is_player_controlled(unit))
                {
                    if (pk::is_alive(unit) and unit.type == 部队类型_战斗 and unit.order != 部队任务_撤退)
                        optimize_target(unit); // 部队目标重新设置函数
                }
            }
        }

        //---------------------------------------------------------------------------
        //                          部队目标重新设置函数
        //---------------------------------------------------------------------------
        void optimize_target(pk::unit @unit)
        {
            int force_id = unit.get_force_id();
            pk::force @force = pk::get_force(force_id);

                //如果进攻的城市已经无法攻下,则撤退,并且呼叫周围5格内的友军一起撤退
            auto scenario_ai_table_unit = pk::get_scenario().ai_table.unit[unit.get_id()];
            if (int(scenario_ai_table_unit.force) == force_id and scenario_ai_table_unit.deploy_type == 部队出征类型_攻击 and pk::is_valid_building_id(scenario_ai_table_unit.deploy_target))
            {
                int unit_deploy_type = scenario_ai_table_unit.deploy_type;
                int deploy_target = scenario_ai_table_unit.deploy_target;

                if (unit.order != 部队任务_撤退 and !unit.action_done and (unit.get_force_id() != pk::get_building(deploy_target).get_force_id() or (unit.order == 部队任务_攻击 and unit.target_type == 部队任务对象_据点 and pk::get_building(unit.target) !is null and unit.get_force_id() != pk::get_building(unit.target).get_force_id())))
                {

                    int attacking_troops = ai::force_attack_base_troops[force_id][deploy_target];
                    int defending_troops = ai::base_around_self_troops[deploy_target] + ch::city_spec_troops(pk::get_building(deploy_target)) / 3 + pk::get_troops(pk::get_building(deploy_target)) * pk::get_building(deploy_target).energy / 120;
                    if (attacking_troops < 30000 and defending_troops>35000 and attacking_troops < defending_troops / 2 and (int(pk::get_building(deploy_target).hp) > int(pk::get_max_hp(pk::get_building(deploy_target)) * 0.6) or int(pk::get_building(deploy_target).hp) > 8000))
                    {
                        pk::building @withdraw_base = find_withdraw_base(unit);
                        if (withdraw_base is null) return;
                        //pk::trace(pk::format("{}部队撤退,原本攻击城市{},我方兵力{},敌方兵力{}", pk::decode(pk::get_name(unit)), pk::decode(pk::get_name(pk::get_building(deploy_target))), attacking_troops, defending_troops));
                        if (pk::is_in_screen(unit.pos))
                            pk::say(pk::encode(pk::format("此战已无胜算,就近向\x1b[2x{}\x1b[0x撤退!", pk::decode(pk::get_name(withdraw_base)))), pk::get_person(unit.leader));

                        pk::set_order(unit, 部队任务_撤退, withdraw_base.pos);
                        pk::run_order(unit);
                        unit.action_done = true;

                        //触发撤退之后,要重新计算
                        for (int j = 0; j < 据点_末; j++)
                        {
                            ai::force_attack_base_troops[force_id][j] = 0;

                        }
                        ai::main.calc_score_unit();

                        pk::array<pk::point> arr_range = pk::range(unit.pos, 1, 5);
                        for (int k = 0; k < int(arr_range.length); k++)
                        {
                            pk::unit @unit_t = pk::get_unit(arr_range[k]);
                            if (!pk::is_alive(unit_t))  continue;
                            if (unit_t.type != 部队类型_战斗) continue;
                            if (!pk::is_alive(pk::get_force(unit_t.get_force_id())) or !pk::is_normal_force(unit_t.get_force_id())) continue;
                            if (unit_t.get_force_id() != force_id) continue;
                            if (unit_t.get_id() == unit.get_id()) continue;
                            if (int(pk::get_scenario().ai_table.unit[unit_t.get_id()].deploy_target) != deploy_target)continue;

                            pk::building @withdraw_base_t = find_withdraw_base(unit_t);
                            if (withdraw_base_t is null) return;
                           // pk::trace(pk::format("{}部队一并撤退,", pk::decode(pk::get_name(unit_t))));
                            if (pk::is_in_screen(unit_t.pos))
                                pk::say(pk::encode(pk::format("此战已无胜算,就近向\x1b[2x{}\x1b[0x撤退!", pk::decode(pk::get_name(withdraw_base_t)))), pk::get_person(unit_t.leader));

                            pk::set_order(unit_t, 部队任务_撤退, withdraw_base.pos);
                            pk::run_order(unit_t);
                            unit_t.action_done = true;
                        }
                        return;
                    }
                }
            }

        }

    //---------------------------------------------------------------------------

        void say_change_target_unit(pk::unit @unit, pk::building @building)
        {
            pk::person @leader = pk::get_person(unit.leader);

            string target_name = ch::get_spec_name(ch::to_spec_id(building.get_id()));

            pk::say(pk::encode(pk::format("大家跟我去占领\x1b[2x{}\x1b[0x!", target_name)), leader);
        }


                // 寻找撤退据点
        int loc_id;
        int service_id;
        pk::building @find_withdraw_base(pk::unit @unit)
        {
            array<pk::building @> dst_base_arr;

            main.loc_id = pk::get_building_id(unit.pos);
            if (main.loc_id < 0 or main.loc_id >= 据点_末)
                return null;
            main.service_id = pk::get_service(unit);

            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @dst_base = pk::get_building(i);

                if (!pk::is_alive(dst_base))
                    continue;

                //太远不行
                if (unit_distance[loc_id][i] > 8)
                    continue;


                if (unit.is_player())
                {
                    pk::district @district = pk::get_district(pk::get_building(i).get_district_id());
                    if (district.no == 1)continue;
                }

                    //判断势力
                if (dst_base.get_force_id() != unit.get_force_id())
                    continue;

                dst_base_arr.insertLast(dst_base);
            }
            if (dst_base_arr.length == 0)return null;
            dst_base_arr.sort(function(a, b) {
                return unit_distance[main.loc_id][a.get_id()] - ((a.get_id() == main.service_id) ? 2 : 0) < unit_distance[main.loc_id][b.get_id()] - ((b.get_id() == main.service_id) ? 2 : 0);
            });

            if (dst_base_arr.length <= 0)
                return pk::get_building(pk::get_service(unit));
            else return  dst_base_arr[0];
        }
    }

    Main main;
}
